﻿/// <summary>
/// fanzhengyong 2016-03-17
/// windows管理器
/// 1、注册所有的window（每一个UI面版整体被称为window）消息
/// 2、把window加到根节点上并显示
/// 3、提供缓存功能
/// 
/// 缓存数据结构说明：
/// UI的缓存是活跃和不活跃的的对象并存，控制缓存大小实际是控制缓存中不活跃的对象个数。
/// 因此，设计的数据结构是包含一个map和队列。map里面存放名字和对象，队列只放不活跃的名字。 
/// 当窗口关闭不会立即Destory，而是设置成不活跃.但缓存中不活跃的不能无限大，所以要以一个
/// 固定大小的缓存在标志哪些是不活跃的名字，以便在删除时候把最先的不活跃的Destory。由于队列
/// 做了名字缓存，取第一个的名字在map中删除，这样在map中删除的查找效率高。
/// </summary>
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace UEngine
{

    public class WindowsManager
    {
        private static WindowsManager m_Instance = null;
        public static WindowsManager Instance()
        {
            if (m_Instance == null)
            {
                m_Instance = new WindowsManager();
            }
            return m_Instance;
        }

        //UI在场景中的根节点(Tag = UIRoot)和上面的transform组件
        private Canvas m_Canvas = null;
        private RectTransform m_CanvasRectTransform = null;

        //缓存数据结构
        private Dictionary<EWindowsName, GameObject> m_winGoPool = new Dictionary<EWindowsName, GameObject>();
        private Queue<EWindowsName> m_deactivePool = new Queue<EWindowsName>();
        private int maxofDeactive = 16;

        public void Init()
        {
            //获取画布
            m_Canvas = GameObject.FindWithTag("UIRoot").GetComponent<Canvas>();
            if (m_Canvas != null)
            {
                m_CanvasRectTransform = m_Canvas.gameObject.GetComponent<RectTransform>();
            }

            //注册所有消息
            PreLoadAllWindows();
        }

        void PreLoadAllWindows()
        {
            RegisteAllWindows.Work();
        }

        public GameObject GetWinGo(EWindowsName name)
        {
            if (m_winGoPool.ContainsKey(name))
            {
                return m_winGoPool[name];
            }

            return null;
        }

        public bool AddWinToRoot(EWindowsName name, GameObject winGo)
        {
            if (
                (winGo == null) ||
                (m_CanvasRectTransform == null)
            )
            {
                return false;
            }

            if (!m_winGoPool.ContainsKey(name))
            {
                m_winGoPool.Add(name, winGo);
            }
            Debug.LogFormat("{0}, {1}", name, winGo.name);
            winGo.transform.SetParent(m_CanvasRectTransform, false);

            return true;
            
        }

        public bool RemoveWin(EWindowsName name)
        {
            if (!m_winGoPool.ContainsKey(name))
            {
                return false;
            }

            if (m_deactivePool.Count == maxofDeactive)
            {
                EWindowsName lastDactive = m_deactivePool.Dequeue();
                if (!m_winGoPool.ContainsKey(lastDactive))
                {
                    return false;
                }

                GameObject go = m_winGoPool[lastDactive];
                GameObject.Destroy(go);
                m_winGoPool.Remove(lastDactive);
            }
            m_deactivePool.Enqueue(name);

            return true;
        }

    }
}

